{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit modOGSSupport;

interface

uses Classes,
     SysUtils,
     modBoardConst,
     modGestionDownload,
     sFonctionsChaines,
     HttpProt,
     LibXmlParser, LibXmlComps,
     modMd5,
     ESBDates,
     modCookies,

     modGalaxiePlanetes,
     modBaseDeDonnesRapport,
     modRapport,

     modGestionDLGZip;

     
     
type

     TOGSAccess = record
         CartographieExport: boolean;
         CartographieImport: boolean;

         RapportEspionnageExport: boolean;
         RapportEspionnageImport: boolean;

         StatistiquesExport: boolean;
         StatistiquesImport: boolean;
     end;


     TOGSMotor = class(TObject)
     private
        // socket
        FWebSocket    : THttpCli;

        // URL du serveur OGSpy
        FURL          : string;

        // page dernièrement téléchargé
        FTempPageWeb  : string;

        // Sauvegarde des cookies
        FCookies : TCollectionCookieInfos;

        FIsLogged: boolean;

        //FServername    : string;       // useless
        FServerVersion : string;
        FAuthorization : TOGSAccess;


        FDebugProc  : TsfcProcStatus;
        FStatusProc : TsfcProcStatus;


        FDateFormat : TFormatSettings;


        procedure DoDebug(Msg: string);
        procedure DoStatus(Msg: string);


        function ParseLogin: integer;

        procedure Init;

        function CartographieBuildDataPacket(item: TGalaxiePlanete): string;
        function RapportsBuildDataPacket(item: TRapportHead): string;


        function PostExportData(data: string): integer;

        function ExtractNextValeurFromTemp: string;
        function ExtractReplyKeyFromToken(Token: string; var Key, Value, Comment: string): integer;

        procedure ShowAutorization;

     public
        Username: string;
        Password: string;
        QuantiteParRequete: integer;

        
        // Définit si on est loggé ou pas
        property IsLogged: boolean read FIsLogged;


        // Acces au socket web (inutile normalement)
        property SocketWeb : THttpCli         read FWebSocket;

        // Procédure de debogage
        property DebugProc : TsfcProcStatus   write FDebugProc;


        // Login
        function Login(URL: string): integer;

        // Exporte la cartographie
        function ExportCartographie(db: TCollectionGalaxiePlanete; DateLimit: int64): integer;

        // Exporte les rappors d'espionnage
        function ExportRapports(db: TCollectionRapportHead; DateLimit: int64): integer;

        constructor Create;
        destructor Destroy; override;
     end;


implementation

uses Windows, gnugettext;

const
   // User Agent
   CNT_OGS_USERAGENT = 'OGSClient';


   // Séparateur items
   CNT_SEPARATEUR_ITEMS = '<->';

   // Sépateur des champs
   CNT_SEPARATEUR_CHAMPS = '<||>';

   CNT_REPLY_ERROR = 'ErrorFatal';

   // Defini si le login a reussi ou non
   CNT_REPLY_LOGIN = 'Login';


   CNT_KEY_SERVER_NAME = 'Servername';
   CNT_KEY_ServerVersion = 'ServerVersion';
   CNT_KEY_ServerInfo = 'ServerInfo';

   // 1: autorisé à exporter les données de cartographie
   // 0: pas autorisé
   CNT_REPLY_ExportCartographie = 'ExportSysAuth';
   CNT_REPLY_ImportCartographie = 'ImportSysAuth';

   // idem mais pour les rapports d'espionnage
   CNT_REPLY_ExportRapportEspionnage = 'ExportSpyAuth';
   CNT_REPLY_ImportRapportEspionnage = 'ImportSpyAuth';

   // idem mais pour les stats
   CNT_REPLY_ExportStatistiques = 'ExportRankAuth';
   CNT_REPLY_ImportStatistiques = 'ImportRankAuth';


const

   //CNT_EXPORT_HEADER = 'galaxy=1,system=2,row=3,moon=4,planetname=5,playername=6,allytag=7,status=8,datetime=9,sendername=10' + CNT_SEPARATEUR_ITEMS;

   CNT_EXPORT_HEADER = 'galaxy=1,system=2,row=3,datetime=4,moon=5,planetname=6,allytag=7,playername=8,status=9,sendername=10' + CNT_SEPARATEUR_ITEMS;

   //galaxy", "system", "row", "datetime", "moon", "planetname", "allytag", "playername", "status", "sendername


   CNT_LOGIN_PHPDATA_FORMAT = 'action=login&name=%s&pass=%s&ogsversion=060602';

   CNT_INDEX_FILE = 'index.php?';



(*

> action=login&name=yyy&pass=xxxxx&ogsversion=060602

<!-- [Login=1] OGame Stratege SharingDB -->
<!-- Servername = OGSPY -->
<!-- ServerVersion = 3.02c -->
<!-- ServerInfo = By Kyser , http://www.ogsteam.fr -->

<!-- [ExportSysAuth=1] You are authorised to export Solar System -->
<!-- [ImportSysAuth=1] You are authorised to import Solar System -->

<!-- [ExportSpyAuth=1] You are authorised to export Spy Reports -->
<!-- [ImportSpyAuth=1] You are authorised to import Spy Reports -->

<!-- [ExportRankAuth=1] You are authorised to export Ranking -->
<!-- [ImportRankAuth=1] You are authorised to import Ranking -->



*)

function TOGSMotor.ExtractReplyKeyFromToken(Token: string; var Key, Value, Comment: string): integer;
var xPos: integer;
    LittleToken: string;
begin
    // exemple de token: "[Login=1] OGame Stratege SharingDB"  Result := 1
    // token type 2:  "ServerVersion = 3.02c"                    Result := 2
    // sion Result := -1

    Result := -1;

    if length(Token) < 3 then begin
       exit;
    end;

    if Token[1] = '[' then begin
       // type 1
       xPos := pos(']', Token);

       if xPos < 1 then begin
          // erreur
          exit;
       end;

       LittleToken := copy(Token, 2, xPos - 2);
       System.Delete(Token, 1, xPos);
       Token := trim(Token);


       xPos := pos('=', LittleToken);
       if xPos < 1 then begin
          // erreur
       end;

       Comment := Token;
       Key := copy(LittleToken, 1, xPos - 1);
       Value := copy(LittleToken, xPos + 1, maxint);

       if (length(Key) > 1) and (length(Value) > 0) then begin
          Result := 1;
       end;

       exit;
    end;


    // sinon peut-être un type 2
    xPos := pos('=', Token);

    if xPos < 1 then begin
       // erreur
       exit;
    end;

    Key   := trim(copy(Token, 1, xPos - 1));
    Value := trim(copy(Token, xPos + 1, maxint));


    if (length(Key) > 1) and (length(Value) > 1) then begin
       Result := 2;
    end;

    

end;

function TOGSMotor.ExtractNextValeurFromTemp: string;
var xPos: integer;
begin

    Result := '';

    xPos := pos('<!-', FTempPageWeb);
    if xPos < 1 then begin
      exit;
    end;

    System.Delete(FTempPageWeb, 1, xPos + 1);

    xPos := pos(' ', FTempPageWeb);
    if xPos < 1 then begin
      exit;
    end;

    System.Delete(FTempPageWeb, 1, xPos);

    xPos := pos('-->', FTempPageWeb);
    if xPos < 1 then begin
      exit;
    end;

    Result := copy(FTempPageWeb, 1, xPos - 1);
    System.Delete(FTempPageWeb, 1, xPos + length('-->') - 1);

    Result := trim(Result);

end;

procedure TOGSMotor.ShowAutorization;
begin

    DoStatus('Autorisation:');

    DoStatus(format(_('Cartographie exportation: %s'), [iif(FAuthorization.CartographieExport, _('Oui'), _('Non'))]));
    DoStatus(format(_('Cartographie importation: %s'), [iif(FAuthorization.CartographieImport, _('Oui'), _('Non'))]));

    DoStatus(format(_('Rapport d''espionnage exportation: %s'), [iif(FAuthorization.RapportEspionnageExport, _('Oui'), _('Non'))]));
    DoStatus(format(_('Rapport d''espionnage importation: %s'), [iif(FAuthorization.RapportEspionnageImport, _('Oui'), _('Non'))]));

    DoStatus(format(_('Statistiques exportation: %s'), [iif(FAuthorization.StatistiquesExport, _('Oui'), _('Non'))]));
    DoStatus(format(_('Statistiques importation: %s'), [iif(FAuthorization.StatistiquesImport, _('Oui'), _('Non'))]));

end;

function TOGSMotor.ParseLogin: integer;
var Token: string;
    NbKeyHandle: integer;
    CriticalKeyFound: integer;

    Key, Value, Comment: string;
    iType: integer;
begin
    Result := -1;

    NbKeyHandle      := 0;
    CriticalKeyFound := 0;

    Token := ExtractNextValeurFromTemp;
    while (length(Token) > 3) do begin

        iType := ExtractReplyKeyFromToken(Token, Key, Value, Comment);

        if iType = 1 then begin
           if SameText(Key, CNT_REPLY_LOGIN) then begin
              if Value = '1' then begin
                 // login ok
                 Result := 1;
              end else begin
                 // erreur
                 Result := 2;
              end;

           end else if SameText(Key, CNT_REPLY_ExportCartographie) then begin
               FAuthorization.CartographieExport := Value = '1';
           end else if SameText(Key, CNT_REPLY_ImportCartographie) then begin
               FAuthorization.CartographieImport := Value = '1';

           end else if SameText(Key, CNT_REPLY_ExportRapportEspionnage) then begin
               FAuthorization.RapportEspionnageExport := Value = '1';
           end else if SameText(Key, CNT_REPLY_ImportRapportEspionnage) then begin
               FAuthorization.RapportEspionnageImport := Value = '1';

           end else if SameText(Key, CNT_REPLY_ExportStatistiques) then begin
               FAuthorization.StatistiquesExport := Value = '1';
           end else if SameText(Key, CNT_REPLY_ImportStatistiques) then begin
               FAuthorization.StatistiquesImport := Value = '1';

           end else begin
              DoStatus('Warning: Clé inconnue: ' + Key + ': ' + Value);
           end;

           if Comment <> '' then begin
              DoStatus('Commentaire: ' + Comment);
           end;

        end else if iType = 2 then begin
           if SameText(Key, CNT_KEY_SERVER_NAME) then begin
              DoStatus(format(_('Serveur: %s'), [Value]));

           end else if SameText(Key, CNT_KEY_ServerVersion) then begin
              DoStatus(format(_('Version: %s'), [Value]));
              FServerVersion := Value;

           end else if SameText(Key, CNT_KEY_ServerInfo) then begin
              DoStatus(format(_('Information: %s'), [Value]));

           end else begin
              DoStatus('Serveur: ' + Key + ': ' + Value);
           end;

        end else begin
           DoDebug('Warning: Token invalide: ' + Token);
        end;
        
        Token := ExtractNextValeurFromTemp;
    end;



    (*
<!-- [Login=1] OGame Stratege SharingDB -->
<!-- Servername = OGSPY -->
<!-- ServerVersion = 3.02c -->
<!-- ServerInfo = By Kyser , http://www.ogsteam.fr -->

<!-- [ExportSysAuth=1] You are authorised to export Solar System -->
<!-- [ImportSysAuth=1] You are authorised to import Solar System -->

<!-- [ExportSpyAuth=1] You are authorised to export Spy Reports -->
<!-- [ImportSpyAuth=1] You are authorised to import Spy Reports -->

<!-- [ExportRankAuth=1] You are authorised to export Ranking -->
<!-- [ImportRankAuth=1] You are authorised to import Ranking -->

*)

end;

function TOGSMotor.RapportsBuildDataPacket(item: TRapportHead): string;
begin

end;

function TOGSMotor.CartographieBuildDataPacket(item: TGalaxiePlanete): string;
begin

//  'galaxy=1,system=2,row=3,datetime=4,moon=5,planetname=6,allytag=7,playername=8,status=9,sendername=10' + CNT_SEPARATEUR_ITEMS;

    Result := '';
    Result := Result + IntToStr(item.Location.Galaxie) + CNT_SEPARATEUR_CHAMPS;
    Result := Result + IntToStr(item.Location.SystemSolaire) + CNT_SEPARATEUR_CHAMPS;
    Result := Result + IntToStr(item.Location.Position) + CNT_SEPARATEUR_CHAMPS;

    Result := Result + DateTimeToStr(UnixToDateTime(item.Date), FDateFormat) + CNT_SEPARATEUR_CHAMPS;

    // lune
    if item.Lune.Surface > 0 then begin
       Result := Result + '1' + CNT_SEPARATEUR_CHAMPS;
    end else begin
       Result := Result + '0' + CNT_SEPARATEUR_CHAMPS;
    end;

    Result := Result + item.NomPlanete + CNT_SEPARATEUR_CHAMPS;
    Result := Result + item.Alliance + CNT_SEPARATEUR_CHAMPS;
    Result := Result + item.Joueur + CNT_SEPARATEUR_CHAMPS;

(*
		if (preg_match("#i#", $values)) $status .= "i";
		if (preg_match("#b#", $values)) $status .= "b";
		if (preg_match("#v#", $values)) $status .= "v";
		if (preg_match("#d#", $values)) $status .= "d";
		if (preg_match("#f#", $values)) $status .= "f";
		if (preg_match("#I#", $values)) $status .= "I";
*)
    if sfcFlagsIsIn(CNT_GALAXIE_FLAGS_MODE_VACANCES, item.Flags) then begin
       Result := Result + 'v';
    end;
    if sfcFlagsIsIn(CNT_GALAXIE_FLAGS_INACTIF_2SEMAINES, item.Flags) then begin
       Result := Result + 'i';
    end;
    if sfcFlagsIsIn(CNT_GALAXIE_FLAGS_INACTIF_4SEMAINES, item.Flags) then begin
       Result := Result + 'I';
    end;
    if sfcFlagsIsIn(CNT_GALAXIE_FLAGS_PROTECTION_NOOB_TROPFAIBLE, item.Flags) then begin
       Result := Result + 'd';
    end;
    if sfcFlagsIsIn(CNT_GALAXIE_FLAGS_PROTECTION_NOOB_TROPFORT, item.Flags) then begin
       Result := Result + 'f';
    end;
    if sfcFlagsIsIn(CNT_GALAXIE_FLAGS_USER_BLOQUE, item.Flags) then begin
       Result := Result + 'b';
    end;

    Result := Result + CNT_SEPARATEUR_CHAMPS;

    Result := Result + Username;

end;

function TOGSMotor.ExportRapports(db: TCollectionRapportHead; DateLimit: int64): integer;
var data: string;
    i, NbCurr: integer;
    pe: PRapportHead;
begin

    if db.Count = 0 then begin
       DoStatus(_('Pas d''élément à exporter'));
       exit;
    end;

    NbCurr := 0;

    for i := 0 to db.Count - 1 do begin
       pe := db.Items[i];


       if mrGetMostRecentDate(pe.DateLastEspionnage) > DateLimit then begin
          Inc(NbCurr);

       end;

    end;


    
end;

function TOGSMotor.ExportCartographie(db: TCollectionGalaxiePlanete; DateLimit: int64): integer;
var data: string;
    i, NbCurr: integer;
    pe: PGalaxiePlanete;
begin


    if db.Count = 0 then begin
       DoStatus(_('Pas d''élément à exporter'));
       exit;
    end;

    NbCurr := 0;

    data := CNT_EXPORT_HEADER;

    for i := 0 to db.Count - 1 do begin
       pe := db.Items[i];

       if pe.Date > DateLimit then begin
          data := data + CartographieBuildDataPacket(pe^) + CNT_SEPARATEUR_ITEMS;

          Inc(NbCurr);



          if NbCurr = QuantiteParRequete then begin
             PostExportData(data);

             data := CNT_EXPORT_HEADER;
             NbCurr := 0;
          end;
       end;

       
    end;

    if NbCurr > 0 then begin
       PostExportData(data);
       data := '';
    end;

end;

function TOGSMotor.PostExportData(data: string): integer;
var phpData: string;
begin

    Result := 0;
    
    FWebSocket.Cookie := FCookies.GetCookieData;

    phpData := 'action=postplanets';

    data := 'data=' + HTTPEncodePHPForParams(data);

    FTempPageWeb := gzhttpGETorPOST_InTamponX(FURL + CNT_INDEX_FILE + phpData, data, FWebSocket);

    DoDebug(FTempPageWeb);

end;



function TOGSMotor.Login(URL: string): integer;
var PhpData: string;
begin

    Result := -1;

    PhpData := format(CNT_LOGIN_PHPDATA_FORMAT, [HTTPEncodePHPForParams(Username), HTTPEncodePHPForParams(Password)]);
    FURL := URL;

    FIsLogged := false;
    FWebSocket.Agent := CNT_OGS_USERAGENT;
    FWebSocket.Cookie := '';

    FCookies.Clear;

    FTempPageWeb := gzhttpGETorPOST_InTamponX(FURL + CNT_INDEX_FILE + PhpData, '', FWebSocket);

    DoDebug(FTempPageWeb);

    if ParseLogin = 1 then begin
       // login ok
       FIsLogged := true;

       // affiche les autorisations
       ShowAutorization;

       Result := 1;
    end;

    FCookies.ParseHeader(FWebSocket.RcvdHeader);

end;

procedure TOGSMotor.Init;
begin
        // Sauvegarde des cookies
        FCookies.Clear;

        FIsLogged := false;

        FServerVersion := '';


        FAuthorization.CartographieExport := false;
        FAuthorization.CartographieImport := false;

        FAuthorization.RapportEspionnageExport := false;
        FAuthorization.RapportEspionnageImport := false;

        FAuthorization.StatistiquesExport := false;
        FAuthorization.StatistiquesImport := false;


end;

constructor TOGSMotor.Create;
begin
    inherited Create;

    FWebSocket    := THttpCli.Create(nil);

    FCookies := TCollectionCookieInfos.Create;

    FDebugProc  := nil;
    FStatusProc := nil;

    QuantiteParRequete := 50;


    //GetLocaleFormatSettings(GetThreadLocale, FDateFormat);
    GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, FDateFormat);


    FDateFormat.DateSeparator := '-';
    FDateFormat.ShortDateFormat :='yyyy-MM-dd';
    FDateFormat.LongDateFormat  := FDateFormat.ShortDateFormat;

    FDateFormat.TimeSeparator := ':';

    FDateFormat.ShortTimeFormat := 'hh:mm:ss';
    FDateFormat.LongTimeFormat  := FDateFormat.ShortTimeFormat;

    FDateFormat.TimeAMString  := '';
    FDateFormat.TimePMString  := '';

    Init;
end;


destructor TOGSMotor.Destroy;
begin
    if FWebSocket <> nil then begin
       FWebSocket.Free;
       FWebSocket := nil;
    end;

    FCookies.Free;

    inherited Destroy;
end;

procedure TOGSMotor.DoDebug(Msg: string);
begin
    if Assigned(FDebugProc) then
       FDebugProc(Msg);

end;

procedure TOGSMotor.DoStatus(Msg: string);
begin
    if Assigned(FDebugProc) then
       FDebugProc(Msg);
end;

end.
